package ru.dasbundos;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

public class ServerThread extends Thread {

	/*
	 * Сокет для чтения/записи данных
	 */
	private Socket mSocket;

	/*
	 * Входной поток сокета. Чтение данных
	 */
	private BufferedReader mIn;

	/*
	 * Выходной поток сокета. Запись данных
	 */
	private PrintWriter mOut;

	/*
	 * Сообщение для прекращения обмена данными
	 */
	private final String mShutdownMessage = "shutdown";
	
	/*
	 * Сообщение для приветствия клиентом сервера
	 */
	private final String mHelloMessage = "hello";
	
	/*
	 * Сообщение для приветствия клиентом сервера
	 */
	private final String mEchoHelloMessage = "Server is greating you";
	
	/*
	 * Задача нахождения кв. корня
	 * */
	private String mSqrtTask = "sqrt";
	
	/*
	 * Параметр задачи
	 * */
	private String mTaskParameter;
	
	/*
	 * Идентификатор клиента
	 */
	private int mClientId = -1;
	
		
	/*
	 * Конструктор
	 */
	public ServerThread(Socket s) throws IOException {
		
		/*
		 * Если любой из нижеприведенных вызовов приведет к возникновению
		 * исключения, то вызывающий метод отвечает за закрытие сокета. В
		 * противном случае, поток закроет его.
		 */

		mSocket = s;
		mIn = new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
		mOut = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream())), true);

		// запуск потока
		start();
	}

	/*
	 * Описание действий потока
	 */
	public void run() {
		String fromClientMessage = "";
		String tokens[];		
		try {
			// читаем, что прислал клиент
			while (true) {
				fromClientMessage = mIn.readLine();
				if (mClientId == -1)
					System.out.println(this.toString() + " recieved from client: " + fromClientMessage);
				else
					System.out.println(this.toString() + " recieved from client "+ mClientId + ": " + fromClientMessage);
				
				// парсим строку, полученную от клиента
				tokens = fromClientMessage.split(" ");
				if (tokens.length < 2) {
					if (tokens[0].equals(mShutdownMessage))	break;					
				}
				else {
					if (tokens[0].equals(mHelloMessage)) {
						mClientId = Integer.parseInt(tokens[1]);
						mOut.println(mEchoHelloMessage + ", client " + mClientId);
						continue;
					}

					/* Создать задачу
					 * отдать на исполнение в пул потоков
					 * дождаться результата
					 * отправить его клиенту
					 * */
					if (tokens[0].equals("sqrt") || tokens[0].equals("sum")) {
											
						ExecutableTask task = new ExecutableTask(tokens[0], tokens[1]);
						Future<String> result = MultiThreadServer.mExecutor.submit(task);
						
						mOut.println("Result for client " + mClientId + " is " + result.get());
						continue;
					}
									
					else
						System.out.println(this.toString() + " unknown command from client " + mClientId);
				}				
			}
			mOut.println("Closing connection to client " + mClientId);
			System.out.println(this.toString() + " closing connection to client " + mClientId);
		}
		catch (IOException e) {
			System.err.println("Client " + mClientId + " was disconnected unexpectedly");
		}
		catch (InterruptedException e) {
			e.printStackTrace();
		}
		catch (ExecutionException e) {
			e.printStackTrace();
		}
		finally {
			try {
				mSocket.close();
				if (MultiThreadServer.mClientsConnected > 0)
					MultiThreadServer.mClientsConnected--;
			}
			catch (IOException e) {
				System.err.println("Socket not closed");
			}
		}
	}

}